/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/




#if !defined(AFX_OBJECTGL_H__4DACBB82_9EFC_11D4_8A95_D4B14EEC3D7F__INCLUDED_)
#define AFX_OBJECTGL_H__4DACBB82_9EFC_11D4_8A95_D4B14EEC3D7F__INCLUDED_


#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <pgl/core/PGLColor.h>
#include <pgl/core/PGLBrush.h>

class CPGLRegion;
class CPGLArchive;
class CPGLObject;
#ifndef PGL_CPGLREGION_SMARTPTR_DEF
	#define PGL_CPGLREGION_SMARTPTR_DEF
	PGL_DECLARE_SMARTPTR( CPGLRegion );
#endif

class CPGLObject;
#ifndef PGL_CPGLOBJECT_SMARTPTR_DEF
	#define PGL_CPGLOBJECT_SMARTPTR_DEF
	PGL_DECLARE_SMARTPTR( CPGLObject );
#endif

/*!
	\defgroup PGLObjectGroup Graphical Objects
\ingroup PGLCoreGroup
*/

/*! \brief A base class to create graphic objects.

\ingroup PGLObjectGroup
This is the base class for all graphical objects. It controls common carateristics
of all graphical objects such as
    - selection state (selected - not selected)
    - visibility state (visible - hidden)
    - an identification number,
    - name and legend string,
    - color (front and fill)


*/
class PGLCORE_EXT_CLASS CPGLObject : public CPGLNode
{
    PGL_DECLARE_DYNCREATE(CPGLObject);
public:
    //! \name Constructors
    //@{
    //! default constructor
    CPGLObject(const CPGLColor& _color=CPGLColor(), const CPGLColor& _FillColor=CPGLColor(1,1,1,1));
    //!  copy constructor
    CPGLObject(const CPGLObject& o){*this=o;};
    //! assignement constructor
    CPGLObject& operator = (const CPGLObject& o);
	//! Destructor
    virtual ~CPGLObject();
	//@}

	//!\name Extent handling
	//@{
    //! virtual function to override in derived classes
    virtual void UpdateExtent(gfxinterface::CGfxInterface& gfx)								{ m_bNeedUpdateExtent=false;}
    //! tells object to update it limits next time getextent is called
    void PostUpdateExtent()																	{   m_bNeedUpdateExtent=true;};
    //! returns true if object needs to update it limits
    bool NeedUpdateExtent()																	{   return m_bNeedUpdateExtent;};
	//! returns extent
	const CPGLRectD& GetExtent() const														{	return m_rExtent;};
	//! returns the smallest rectangle containing the object extent and rExtent
	virtual void GetUnionExtent(gfxinterface::CGfxInterface& gfx, CPGLRectD& rExtent)		{		if (NeedUpdateExtent())	UpdateExtent(gfx);};

	//! returns left coordinate (world coordinate)
	double GetLeft() const			{	return m_rExtent.left;};
	//! returns right coordinate (world coordinate)
	double GetRight() const			{	return m_rExtent.right;};
	//! returns bottom coordinate (world coordinate)
	double GetBottom() const		{	return m_rExtent.bottom;};
	//! returns top coordinate (world coordinate)
	double GetTop() const			{	return m_rExtent.top;};
	//! returns width coordinate (world coordinate)
	double GetWidth() const			{	return m_rExtent.GetWidth();};
	//! returns height coordinate (world coordinate)
	double GetHeight() const		{	return m_rExtent.GetHeight();};
	//@}

	//! \name Scripting methods
	//@{
	//! property enumeration
	enum EObjectProp
	{
		ObjectPropUnknow=0,
		//! Corresponding string: name
		ObjectPropName=1,
		//! Corresponding string: description
		ObjectPropDescription=2,
		//! Corresponding string: color
		ObjectPropColor=3,
		//! Corresponding string: brush
		ObjectPropBrush=4,
		//! Corresponding string: visible
		ObjectPropVisible=5,
		//! Corresponding string: layer
		ObjectPropLayer=6
	};
	//! A pair property enum and description
	typedef std::pair< int, CString> PropertyPair;
	//! Property map
	typedef std::map< CString, PropertyPair > PropertyMap;
	/*!\brief Sets properties and values in a command line fashion

	\param szPropAndValues command line of property=value pairs
	*/
	virtual void Set( LPCTSTR szPropAndValues );
	/*! \brief Adding other scripting methods
	*/
	static EObjectProp StringToObjectProp ( LPCTSTR szProp);
	virtual bool SetProperty( LPCTSTR szProp, LPCTSTR szValue);
	virtual bool Get( LPCTSTR szProp, CString& str);
	virtual void Help( CString& str) const;
	/*! \brief Parse brush format
	*/
	void ParseBrushFormat( LPCTSTR szValue );
	//@}

	//! \name GUI
	//@{
    //! adds context menu items...
    virtual void AddContextMenuItems(CMenu* pMenu){};
    //! adds the object property page to the property dialog
    virtual void AddPropertyPage(CPropertySheet* pPropSheet);
    //! adds the object in the tree
	virtual HTREEITEM AddPropTree(CTreeCtrl* pTree, HTREEITEM hParent);
    //! createa Property sheet dialog, adds all parent property page and DoModal...
    virtual void ShowModalPropertySheet(){};
	//@}


	//! name Main Drawing Functions
	//@{
	//! Make front color current
	void MakeFrontColorCurrent(gfxinterface::CGfxInterface& gfx)	{	gfx.SetColor(m_cColor.GetRed(),m_cColor.GetGreen(),m_cColor.GetBlue(),m_cColor.GetAlpha());	};

    //! Drawing main function
    virtual void PlotGfx(gfxinterface::CGfxInterface& gfx);
	//! Drawing legend main function
    virtual void PlotLegendGfx(gfxinterface::CGfxInterface& gfx, const CPGLRectD& rBox);
	//@}

	//! \name Visibility and selection state
	//@{
    //! set the object as selected
    void Select() {m_bSelected=TRUE;};
    //! set the object as not selected
    void Deselect() { m_bSelected=FALSE;};
    //! returns true if the object is selected, false otherwise
    bool IsSelected() { return m_bSelected;};
    //! switch selection state
    void SwitchSelectionState() { m_bSelected=!m_bSelected;};

    //! set the object as visible
    void Show(bool show = TRUE) { m_bVisible=show;};
    //! set the object as hidden
    void Hide() { m_bVisible=FALSE;};
    //! returns true if the object is visible, false otherwise
    bool IsVisible() const { return m_bVisible;};
    //! switch visibility state
    void SwitchVisibilityState() { m_bVisible=!m_bVisible;};
	//@}

	//! \name Layer
	//@{
	//! returns current layer of object
	gfxinterface::ELayer GetLayer() const			{ return m_eLayer;};
	//! sets current layer
	void SetLayer(gfxinterface::ELayer eLayer)	{ m_eLayer = eLayer;};
	//! returns true if in current layer, of layer disabled.
	bool IsInLayer(gfxinterface::ELayer eLayer)	const {	return (eLayer==gfxinterface::LayerDisabled || m_eLayer==eLayer);};
	//@}

	//! \name Name and description
	//@{
    //! sets the name of the object
    void SetName(LPCTSTR _name)					{ m_sName=_name;};
    //! returns the name
    LPCTSTR GetName() const						{ return m_sName;};
    //! sets the name of the object
    void SetDescription(LPCTSTR _szDescription)	{ m_sDescription=_szDescription;};
    //! returns the description
    LPCTSTR GetDescription() const				{ return m_sDescription;};
	//! returns the string to be displayed in the legend
	LPCTSTR GetLegendString() const					{ return (m_sDescription.IsEmpty()) ? m_sName : m_sDescription;};
	//@}

	
	//! \name Setter and getter for the parent region
	//@{
	//! Returns pointer to parent region
	CPGLRegionStPtr GetParent();
	//! Sets pointer to parent region
	void SetParent(CPGLRegionStPtr pParent);
	//@}

	//! \name Front Color
	//@{
    //! sets red component of object's color (must be in [0,1])
    void SetRed(float red) { m_cColor.SetRed(red);}; 
    //! sets green component of object's color (must be in [0,1])
    void SetGreen(float green) { m_cColor.SetGreen(green);}; 
    //! sets blue component of object's color (must be in [0,1])
    void SetBlue(float blue) { m_cColor.SetBlue(blue);}; 
    //! sets alpha component of object's color (must be in [0,1])
    void SetAlpha(float alpha) { m_cColor.SetAlpha(alpha);}; 

    //! sets the object's color
    void SetColor(const CPGLColor& _color)										{ m_cColor=_color;};
    //! sets the object's color
    void SetColor(float red=1.0,float green=1.0,float blue=1.0,float alpha=1.0) { m_cColor=CPGLColor(red,green,blue,alpha);};
    //! returns the object color
    const CPGLColor& GetColor() const											{ return m_cColor;};
    //! returns the object color
    CPGLColor& GetColor()														{ return m_cColor;};
	//@}

	//! \name Fill Brush
	//@{
	//! returns the object color
    const CPGLBrushPtr GetFillBrush() const	{	return m_pBrushFill;};
	//! returns current fill brush
    CPGLBrushPtr GetFillBrush()				{	return m_pBrushFill;};
	//! sets current fill brush (makes a copy)
	void SetBrush( CPGLBrushPtr pBrush);

	//! Sets fill color
	void SetSolidFillColor(const CPGLColor& col);
	//! Sets fill color
    void SetSolidFillColor(float red=1.0,float green=1.0,float blue=1.0,float alpha=1.0);
	void SetFrontToFillColor(gfxinterface::CGfxInterface &gfx)					{	gfx.SetFillColor(m_cColor.GetRed(),m_cColor.GetGreen(),m_cColor.GetBlue(),m_cColor.GetAlpha());};	
	void SetFrontToFillColor(gfxinterface::CGfxInterface &gfx, double alpha)	{	gfx.SetFillColor(m_cColor.GetRed(),m_cColor.GetGreen(),m_cColor.GetBlue(),alpha);};	
	//@}

    //! sets the selection color (this is a static property)
    static void SetSelectionColor(const CPGLColor& _selectionColor) { m_selectionColor=_selectionColor;};
    //! gets the selection color
    static CPGLColor GetSelectionColor() { return m_selectionColor;};

	//! returns the bitmap.
	virtual HBITMAP GetBitmap() {	return m_hBitmap;};

	//! \name Serialization and debugging
	//@{
	//! Serialize object in XML format to archive
	virtual void SerializeXML(CPGLArchive& ar);
	//! Serialize XML scheme to archive
//	virtual void SerializeXSD(CPGLArchive& ar);
#ifdef _DEBUG
    virtual void Dump( CDumpContext& dc ) const;
    virtual void AssertValid() const;    // Override
#endif
    //@}
    
	//! Sets the extent of the object
	void SetExtent(const CPGLRectD& rExtent)	{	m_rExtent = rExtent;};
protected:
	virtual void PreparePropertyMap();
	static PropertyMap m_mProps;

	//! Load the bitmap
	void LoadBitmap(DWORD ID_RESSOURCE);
private:
	friend class CPGLObjectPool;

    /*! \name Class Private Parameters*/
    //@{
	//! a small bitmap describing the object...
	HBITMAP m_hBitmap;
    //! extent of the object left, right, bottom, top
	CPGLRectD m_rExtent;
    //! visibility state
    bool m_bVisible;
    //! selection state
    bool m_bSelected;
	//! layer
	gfxinterface::ELayer m_eLayer;
    //! object's name
    CString m_sName;
    //! object's name
    CString m_sDescription;
    //! object's color
    CPGLColor m_cColor;
	//! Fill color
	CPGLBrushPtr m_pBrushFill;
    //! object needs to update it's limits
    bool m_bNeedUpdateExtent;
	//! Pointer to parent region
	CPGLRegionStPtr m_pParent;
    //! the selection color
    static CPGLColor m_selectionColor;
	//@}
};


#endif // !defined(AFX_OBJECTGL_H__4DACBB82_9EFC_11D4_8A95_D4B14EEC3D7F__INCLUDED_)
